Vue的iframe嵌套问题处理

vue嵌套iframe一系列问题

最近在项目中遇到一个需求需要在一个项目中直接引用另一个项目,尝试各种情况无果后选择了iframe。现将调用过程中遇到的问题做一个分享。

router.go()的使用
  此情况主要适用于更改iframe中src值以后导致的路由跳转混乱。

  详细描述:当多次更改iframe->src属性后,调用router.go(-1),不能实现路由后退上一级,而是将iframe当作一个窗口文档,调用了该窗口文档的window.history.go(-1),并未更改父级项目的路由后退功能。

  解决办法:

  不通过改变iframe->src属性值去访问具体内容,采用window.location.replace(url)更改iframe将访问的内容,具体代码如下:
A.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<iframe ref="iframe" scrolling="auto" width="100%" height="100%" frameborder="0" ></iframe>
</template>
<script>
export default {
name: 'ComponentsName',
data() {
return {
url: ''
}
},
watch: {
url(val) {
if (val) {
this.$refs.iframe.contentWindow.location.replace(val)
}
}
}
}
</script>

注意ref=”iframe” 中iframe,的名字若在多个页面情况下,建议用不同的名称,不然打包之后会报错
this.$refs.iframe.contentWindow.location.replace(val) 同样也需要修改

通信(父页面和子页面相互通信)

  两个项目之间相互通信,涉及到跨域问题,子页面不能直接调用父页面的方法,父页面同样不能调用子页面的方法。

  错误详情:Error in created hook: “SecurityError: Blocked a frame with origin “http://*” from accessing a cross-origin frame.”

  解决办法: postMessage

  window.postMessage() 方法可以安全地实现跨源通信。该方法被调用时,会在所有页面脚本执行完毕之后向目标窗口派发一个MessageEvent消息。代码如下:

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<title>Post Message</title>
</head>
<body>
<div>
<div id="color">Frame Color</div>
</div>
<div>
<iframe id="child" width="50%" src="http://172.16.110.188/test.html" height="50vw" scrolling="auto" frameborder="0"></iframe>
</div>
<script type="text/javascript">
window.onload=function(){
document.getElementById('child').contentWindow.postMessage('getcolor','http://172.16.110.188');
}
window.addEventListener('message',function(e){
var color=e.data;
document.getElementById('color').style.backgroundColor=color;
},false);
</script>
</body>
</html>

test.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!doctype html>
<html>
<head>
<style type="text/css">
html,body{
height:100%;
margin:0px;
}
#container{
widht:100%;
height:100%;
background-color:rgb(204, 102, 0);
}
</style>
</head>
<body style="height:100%;">
<div id="container" onclick="changeColor();">
click to change color
</div>
<script type="text/javascript">
var container=document.getElementById('container');
window.addEventListener('message',function(e){
if(e.source!=window.parent) return;
var color=container.style.backgroundColor;
window.parent.postMessage(color,'*');
},false);
function changeColor () {
var color=container.style.backgroundColor;
if(color=='rgb(204, 102, 0)'){
color='rgb(204, 204, 0)';
}else{
color='rgb(204,102,0)';
}
container.style.backgroundColor=color;
window.parent.postMessage(color,'*');
}
</script>
</body>
</html>

上面的例子实现了两个不同域的页面之间的通信。但由于我们此处用的是动态更改iframe.contentWindow.location来访问的内容,如果此处父页面要向子页面发起通信需要在iframe中页面加载完毕以后,不然子页面无法获取到通信数据。

应用场景
子页面需要调用父页面的方法或则使用父页面的数据时候,我们可以在子页面向父页面发起通信,让父页面调用该方法,或让父页面将数据传输过来。

注意事项
  postMessage支持对象传递,但不是所有浏览器都支持对象传递,在使用中还是使用字符串传值更好。

继开 wechat
欢迎加我的微信,共同交流技术